#include "OpcodeEditor.h"
#include "ui_OpcodeEditor.h"
#include <QStandardItemModel>
#include "swf/abc/Opcode.h"
#include "swf/SWFInputStream.h"
#include "swf/abc/AS3Model.h"
#include "model/SWFTreeModel.h"
#include "model/OpcodeItem.h"

OpcodeEditor::OpcodeEditor(AS3Method* mb, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::OpcodeEditor),
	_method(mb)
{
    ui->setupUi(this);

	QStringList headList;
	headList << "Offset" << "Binary" << "Opcode" << "Params";
	_model = new SWFTreeModel();
	_model->setHeaderStringList(headList);

	if (mb != nullptr)
	{
		std::vector<OpcodeInstruction*> instVec;
		AS3MethodBody* body = mb->getBody();
		SWFInputStream input(body->data, body->length);

		OpcodeAnalyzer a;
		CpoolInfo* pool = body->getABCFile()->getRawCpool();
		a.analyze(pool, &input, instVec);

		size_t offset = 0;
		OpcodeItem* prevItem = nullptr;
		for (auto ins : instVec)
		{
			OpcodeItem* item = new OpcodeItem(ins, pool);
			item->setOffset(offset);
			_model->appendRow(item);

			if (prevItem)
			{
				prevItem->next = item;
				item->prev = prevItem;
			}
			offset += ins->dataLen;
		}

		ui->tableView->setModel(_model);
	}
}

OpcodeEditor::~OpcodeEditor()
{
    delete ui;
}

void OpcodeEditor::onContextMenuRequested( const QPoint& )
{
	auto index = ui->tableView->currentIndex();
	auto item = _model->itemFromIndex(index);
	if (item != nullptr)
	{
		QMenu* menu = item->requestContextMenu();
		if (menu != nullptr)
		{
			menu->exec(QCursor::pos());
		}
	}
}

const QString OpcodeEditor::getEditorName() const 
{
	return _method->getShortName().c_str();
}

QWidget* OpcodeEditor::asWidget() const 
{
	return (QWidget*)this;
}
